/*
 * SearchGUI.java
 *
 * Created on Feb 24, 2011, 1:20:04 PM
 */


package org.workplicity.cia.ui;

//import java.util.ArrayList;
//import java.awt.event.ItemEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.workplicity.cia.table.SearchResultsTableModel;
import org.workplicity.cia.worklet.ElogsWorklet;
import org.workplicity.elog.entry.Elog;
import org.workplicity.elog.entry.ElogUser;
import org.workplicity.task.NetTask;
import org.workplicity.util.Helper;
import org.workplicity.util.WorkDate;
import org.workplicity.worklet.WorkletContext;
import java.beans.Introspector;
import java.beans.IntrospectionException;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import org.workplicity.elog.entry.Handoff;
import java.util.regex.Pattern;



/**
 *
 * @author Elog Team
 */
public class SearchGUI extends javax.swing.JFrame {
    private ElogUser user = null;

    private ElogsWorklet worklet = ElogsWorklet.getInstance();
    ArrayList<ElogUser> users;
    private WorkletContext context = worklet.getContext();
    private WorkDate startDate;
    private WorkDate endDate;
    private int id;
    private String keyword;
    private Elog.Type type = Elog.Type.ANY;
    private Elog.Status status = Elog.Status.ANY;
    private String selectedUser;
    private ArrayList<Elog> elogs = new ArrayList<Elog>();
    private ArrayList<Handoff> handoffs = new ArrayList<Handoff>();


    /** Creates new form SearchGUI */
    public SearchGUI() {
        initComponents();

        int resultsHeight = 410;
        if(System.getProperty("os.name").startsWith("Mac")){
            resultsHeight = 450;
        }

        this.setSize(330, resultsHeight);
        this.setLocationRelativeTo(null);
        
        user = (ElogUser) Helper.whoAmI(context);
        this.setTitle("Netlog (" + user.getLogname() + ") >> Search");

        populateUserCombo();

        Calendar cal = Calendar.getInstance();

        // Sets default start date to today's date
        Date queryStartDate = cal.getTime();
        String dateStringStart = "";
        dateStringStart = dateFormat.format(queryStartDate);
        startTimeTextField.setText(dateStringStart);
        startCalendarButton.setTargetDate(queryStartDate);

        // Sets default end date to yesterday's date
        cal.add(Calendar.DAY_OF_YEAR, -1);
        Date queryEndDate = cal.getTime();
        String dateStringEnd = "";
        dateStringEnd = dateFormat.format(queryEndDate);
        endTimeTextField.setText(dateStringEnd);
        endCalendarButton.setTargetDate(queryEndDate);

        searchByIdTextField.addFocusListener(new FocusListener() {
            //This makes the default text disappear for the field on the first click
            boolean focusedOnce = false;
            @Override
            public void focusGained(FocusEvent e) {
                if (!focusedOnce) {
                    searchByIdTextField.setText("");
                    focusedOnce = true;
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
            }
        });

        keywordTextField.addFocusListener(new FocusListener() {
            //This makes the default text disappear for the field on the first click
            boolean focusedOnce = false;
            @Override
            public void focusGained(FocusEvent e) {
                if (!focusedOnce) {
                    keywordTextField.setText("");
                    focusedOnce = true;
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
            }
        });
    }

    //Validate the dates
    private boolean validateDates() {
        boolean validates = true;
        String startDateString = startTimeTextField.getText();
        String endDateString = endTimeTextField.getText();
        startDate = Helper.toDate(startDateString);
        if (startDate == null) {
            String message = "Start date must be in mm / dd / yyyy format.";
            JOptionPane.showMessageDialog(this, message, "Error",
                    JOptionPane.ERROR_MESSAGE);
            validates = false;
        }

        endDate = Helper.toDate(endDateString);
        if (endDate == null) {
            String message = "End date must be in mm / dd / yyyy format.";
            JOptionPane.showMessageDialog(this, message, "Error",
                    JOptionPane.ERROR_MESSAGE);
            validates = false;
        }

        if (startDate != null && endDate != null) {
            int dateComparison = startDate.compareTo(endDate);
            if (dateComparison == -1) {
                String message = "Start date must be later than or equal to the end date.";
                JOptionPane.showMessageDialog(this, message, "Error",
                        JOptionPane.ERROR_MESSAGE);
                validates = false;
            }
        }

        return validates;
    }

    /**
     * This method ensures the search can be carried out.
     * @return whether there were no validation errors
     */
    private boolean validQuery() {
        //If we get no errors, we're good to search.
        boolean valid = true;
        //If search by id is checked, and it does not validate, give an error,
        //and terminate the search
        if (searchByIdCheckBox.isSelected()) {
            try {
                id = Integer.parseInt(searchByIdTextField.getText());
                if (id < 0) {
                    throw new NumberFormatException();
                }

            }
            catch (NumberFormatException ex) {
                String message = "Id number must be a valid positive integer.";
                JOptionPane.showMessageDialog(this, message, "Error",
                    JOptionPane.ERROR_MESSAGE);
                valid = false;
            }
        }
        //Otherwise the search by keyword is enabled and must be checked
        //if blank throw an exception
        else
            try{
                 keyword = keywordTextField.getText().replace(".", "").trim();
                 if(keyword.equals("")){
                    throw new Exception();
                 }
            }
            catch (Exception keyword){
                String message = "Invalid Keyword.";
                JOptionPane.showMessageDialog(this, message, "Error",
                        JOptionPane.ERROR_MESSAGE);
                valid = false;

            }

        if (!validateDates())
            valid = false;

        selectedUser = userComboBox.getSelectedItem().toString();

        return valid;
    }
    /**
     * Query Accounts Repository to get Users, sort names in alphabetical order
     * and add them to the User ComboBox drop down.
     */
    private void populateUserCombo() {
         // query
         String criteria = "/list";
         users = Helper.query(NetTask.REPOS_ACCOUNTS, criteria, context);

         // get names from User objects
         String[] userArray = new String[users.size()];
         int index = 0;
         for(ElogUser currentUser : users){
             userArray[index++] = currentUser.getLogname();
         }

         // sort alphabetically
         Arrays.sort(userArray);

         // add user names to combo box
         for(String userName : userArray){
            userComboBox.addItem(userName);
         }

         // select default value
         this.userComboBox.setSelectedItem("All");
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        jFrame1 = new javax.swing.JFrame();
        jFrame2 = new javax.swing.JFrame();
        goButton = new javax.swing.JButton();
        findWholeWordsOnlyCheckBox = new javax.swing.JCheckBox();
        cancelButton = new javax.swing.JButton();
        typeComboBox = new javax.swing.JComboBox();
        typeLabel = new javax.swing.JLabel();
        keywordTextField = new javax.swing.JTextField();
        keywordLabel = new javax.swing.JLabel();
        searchByIdTextField = new javax.swing.JTextField();
        matchCaseCheckBox = new javax.swing.JCheckBox();
        searchHandoffsCheckBox = new javax.swing.JCheckBox();
        searchByIdCheckBox = new javax.swing.JCheckBox();
        endTimeLabel = new javax.swing.JLabel();
        userComboBox = new javax.swing.JComboBox();
        endTimeTextField = new javax.swing.JTextField();
        searchByIdLabel = new javax.swing.JLabel();
        startTimeLabel = new javax.swing.JLabel();
        startTimeTextField = new javax.swing.JTextField();
        statusLabel = new javax.swing.JLabel();
        statusComboBox = new javax.swing.JComboBox();
        endCalendarButton = new org.jbundle.thin.base.screen.jcalendarbutton.JCalendarButton();
        startCalendarButton = new org.jbundle.thin.base.screen.jcalendarbutton.JCalendarButton();

        javax.swing.GroupLayout jFrame1Layout = new javax.swing.GroupLayout(jFrame1.getContentPane());
        jFrame1.getContentPane().setLayout(jFrame1Layout);
        jFrame1Layout.setHorizontalGroup(
            jFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame1Layout.setVerticalGroup(
            jFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jFrame2Layout = new javax.swing.GroupLayout(jFrame2.getContentPane());
        jFrame2.getContentPane().setLayout(jFrame2Layout);
        jFrame2Layout.setHorizontalGroup(
            jFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame2Layout.setVerticalGroup(
            jFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setAlwaysOnTop(true);
        setResizable(false);

        goButton.setFont(new java.awt.Font("Tahoma", 0, 12));
        goButton.setText("Go");
        goButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                goButtonActionPerformed(evt);
            }
        });

        findWholeWordsOnlyCheckBox.setFont(new java.awt.Font("Tahoma", 0, 12));
        findWholeWordsOnlyCheckBox.setText("Find whole words only");

        org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, searchByIdCheckBox, org.jdesktop.beansbinding.ELProperty.create("${!selected}"), findWholeWordsOnlyCheckBox, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        cancelButton.setFont(new java.awt.Font("Tahoma", 0, 12));
        cancelButton.setText("Cancel");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });

        typeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "ANY", "UNUSUAL", "NORMAL" }));
        typeComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                typeComboBoxActionPerformed(evt);
            }
        });

        typeLabel.setFont(new java.awt.Font("Tahoma", 0, 12));
        typeLabel.setText(" Type: ");

        keywordTextField.setFont(new java.awt.Font("Tahoma", 0, 12));
        keywordTextField.setText("Enter text");

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, searchByIdCheckBox, org.jdesktop.beansbinding.ELProperty.create("${!selected}"), keywordTextField, org.jdesktop.beansbinding.BeanProperty.create("editable"));
        bindingGroup.addBinding(binding);
        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, searchByIdCheckBox, org.jdesktop.beansbinding.ELProperty.create("${!selected}"), keywordTextField, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        keywordLabel.setFont(new java.awt.Font("Tahoma", 0, 12));
        keywordLabel.setText("Keyword: ");

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, searchByIdCheckBox, org.jdesktop.beansbinding.ELProperty.create("${!selected}"), keywordLabel, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        searchByIdTextField.setFont(new java.awt.Font("Tahoma", 0, 12));
        searchByIdTextField.setText("Enter a number");

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, searchByIdCheckBox, org.jdesktop.beansbinding.ELProperty.create("${selected}"), searchByIdTextField, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        matchCaseCheckBox.setFont(new java.awt.Font("Tahoma", 0, 12));
        matchCaseCheckBox.setText("Match case");

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, searchByIdCheckBox, org.jdesktop.beansbinding.ELProperty.create("${!selected}"), matchCaseCheckBox, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        searchHandoffsCheckBox.setFont(new java.awt.Font("Tahoma", 0, 12));
        searchHandoffsCheckBox.setText("Search handoffs");

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, searchByIdCheckBox, org.jdesktop.beansbinding.ELProperty.create("${!selected}"), searchHandoffsCheckBox, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        searchByIdCheckBox.setText("Search by id:");
        searchByIdCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                searchByIdCheckBoxActionPerformed(evt);
            }
        });

        endTimeLabel.setFont(new java.awt.Font("Tahoma", 0, 12));
        endTimeLabel.setText("End: ");

        userComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "All" }));
        userComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                userComboBoxActionPerformed(evt);
            }
        });

        endTimeTextField.setFont(new java.awt.Font("Tahoma", 0, 12));

        searchByIdLabel.setFont(new java.awt.Font("Tahoma", 0, 12));
        searchByIdLabel.setText("User: ");

        startTimeLabel.setFont(new java.awt.Font("Tahoma", 0, 12));
        startTimeLabel.setText(" Start: ");

        startTimeTextField.setFont(new java.awt.Font("Tahoma", 0, 12));

        statusLabel.setFont(new java.awt.Font("Tahoma", 0, 12));
        statusLabel.setText("Status:");

        statusComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "ANY", "DONE", "NOTDONE" }));
        statusComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                statusComboBoxActionPerformed(evt);
            }
        });

        endCalendarButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                endCalendarButtonActionPerformed(evt);
            }
        });
        endCalendarButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                endCalendarButtonFocusLost(evt);
            }
        });
        endCalendarButton.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                endCalendarButtonPropertyChange(evt);
            }
        });

        startCalendarButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startCalendarButtonActionPerformed(evt);
            }
        });
        startCalendarButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                startCalendarButtonFocusLost(evt);
            }
        });
        startCalendarButton.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                startCalendarButtonPropertyChange(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(statusLabel)
                            .addComponent(startTimeLabel)
                            .addComponent(endTimeLabel)
                            .addComponent(keywordLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(searchByIdCheckBox)
                            .addComponent(searchByIdLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(typeLabel))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(statusComboBox, 0, 211, Short.MAX_VALUE)
                            .addComponent(searchByIdTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(userComboBox, 0, 211, Short.MAX_VALUE)
                            .addComponent(keywordTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 211, Short.MAX_VALUE)
                            .addComponent(typeComboBox, 0, 211, Short.MAX_VALUE)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(startTimeTextField)
                                    .addComponent(endTimeTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 92, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(endCalendarButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(startCalendarButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(goButton, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(searchHandoffsCheckBox)
                    .addComponent(matchCaseCheckBox)
                    .addComponent(findWholeWordsOnlyCheckBox))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(searchByIdLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(userComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(searchByIdCheckBox)
                    .addComponent(searchByIdTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(keywordLabel)
                    .addComponent(keywordTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(typeLabel)
                    .addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 16, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(statusComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(statusLabel))
                .addGap(14, 14, 14)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(startTimeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(startTimeLabel)
                    .addComponent(startCalendarButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(endTimeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(endCalendarButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(endTimeLabel))
                .addGap(18, 18, 18)
                .addComponent(searchHandoffsCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(matchCaseCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(findWholeWordsOnlyCheckBox)
                .addGap(7, 7, 7)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cancelButton)
                    .addComponent(goButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        bindingGroup.bind();
    }// </editor-fold>//GEN-END:initComponents

    private void searchByIdCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchByIdCheckBoxActionPerformed
        // TODO add your handling code here:
}//GEN-LAST:event_searchByIdCheckBoxActionPerformed

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        dispose();
}//GEN-LAST:event_cancelButtonActionPerformed

    private void typeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_typeComboBoxActionPerformed
        String selectedItem = (String) typeComboBox.getSelectedItem();
        type = Elog.Type.valueOf(selectedItem);
}//GEN-LAST:event_typeComboBoxActionPerformed

    private void goButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goButtonActionPerformed
       
        //We're not good to go, so don't search.
        if (!validQuery())
            return;
        final JFrame table = this;

        SwingUtilities.invokeLater(new Runnable(){

            public void run() {
                elogs = new ArrayList<Elog>();
                handoffs = new ArrayList<Handoff>();
                WorkletContext context = WorkletContext.getInstance();

                //Aside from id, the criteria will be the same regardless of
                //search by id or search by keyword, so create it once.
                String criteria = "/list [ updateDate <= ";
                criteria += startDate;
                criteria += " and updateDate >= ";
                criteria += endDate;
                if(type != Elog.Type.ANY){
                   criteria += " and type = '";
                   criteria += type.toString()+ "'";
                }
                if(status != Elog.Status.ANY){
                   criteria += " and status = '";
                   criteria += status.toString()+ "'";
                }

                if (searchByIdCheckBox.isSelected()) {
                    //searching by ID, so append the ID to the query
                    criteria += " and id = ";
                    criteria += id;
                    criteria += " ]";
                    elogs = getUserElogs(criteria);
                } else {
                    //No more criteria to be assigned, so close the query
                    criteria += " ]";
                    elogs = getUserElogs(criteria);
                    String keyword = keywordTextField.getText();
                    boolean caseMatch;
                    boolean wholeWords;
                    
                    if (matchCaseCheckBox.isSelected())
                        caseMatch = true;
                    else
                        caseMatch = false;
                    
                    //set the necessary variables for the search methods
                    if (findWholeWordsOnlyCheckBox.isSelected())
                        wholeWords = true;
                    else
                        wholeWords = false;

                    //First run the search on elogs and return the results to
                    //the elogs arraylist.
                    elogs = keywordElogSearch(elogs, keyword, caseMatch, wholeWords);

                    //next, if search handoffs is checked, then search the
                    //handoffs, then for each element in the arraylist, get the
                    //associated elog entry.
                    if (searchHandoffsCheckBox.isSelected()){
                        handoffs = getUserHandoffs(criteria);
                        handoffs = keywordHandoffSearch(handoffs, keyword, caseMatch, wholeWords);

                        for(Handoff handoff : handoffs)
                            elogs.add((Elog)Helper.fetch(handoff.getReposTitle(), handoff.getElogId(),context));
                    }
                }

                //launch the results table.
                launchResults(table);
            }
            
        });
        
    }//GEN-LAST:event_goButtonActionPerformed

    /*
     * Method searches all of the Elogs in the arraylist based on the search
     * criteria.  It does so by pulling the class info and looping through the
     * properties and searching any string type for the input.
     */
    private ArrayList<Elog> keywordElogSearch(ArrayList<Elog> list, String keyword,
                                        boolean caseMatch, boolean wholeWords){

        ArrayList<Elog> temp = new ArrayList<Elog>(list);


        try {
            //get the list of properties for the class
            BeanInfo elogInfo = Introspector.getBeanInfo(Elog.class);

            for (Elog item : temp){
                boolean found = false;

                    for (PropertyDescriptor pd : elogInfo.getPropertyDescriptors()) {
                        //for the current property, retrieve its getter
                        Method method = pd.getReadMethod();
                        if (pd.getPropertyType().equals(java.lang.String.class)) {

                            //begin checking the parameters, all self explanatory.
                            if (caseMatch == true && wholeWords == true) {
                                Pattern p = Pattern.compile(".*\\W?\\Q"+keyword +"\\E\\W?.*");
                                Matcher m = p.matcher(method.invoke(item).toString());
                                if (m.matches())
                                    found = true;
                            }
                            else if (caseMatch == false && wholeWords == true) {
                                Pattern p = Pattern.compile(".*\\W?\\Q"+keyword+"\\E\\W?.*", Pattern.CASE_INSENSITIVE);
                                Matcher m = p.matcher(method.invoke(item).toString());
                                System.out.println(m);
                                System.out.println(method.invoke(item).toString());
                                if (m.matches()){
                                    System.out.println("match");
                                    found = true;
                                }
                            }
                            else if (caseMatch == true && wholeWords == false
                                    && method.invoke(item).toString().contains(keyword)) {
                                found = true;
                            }
                            else if (caseMatch == false && wholeWords == false
                                    && method.invoke(item).toString().toLowerCase().contains(keyword.toLowerCase())) {
                                found = true;
                            }
                        }
                    }

                //if there are no fields that match, then the elog is removed
                System.out.println(found);
                if (found == false){
                    list.remove(item);
                }
            }
            
        } catch (IntrospectionException ex) {
            System.out.println("!!!!!!!");
            Logger.getLogger(SearchGUI.class.getName()).log(Level.SEVERE, null, ex);
        } finally{
            //ALWAYS return elogs back to the calling method.
            return list;
        }
    }

/*
 * Method searches all of the Handoffs in the arraylist based on the search
 * criteria.  It does so by pulling the class info and looping through the
 * properties and searching any string type for the input.
 */

private ArrayList<Handoff> keywordHandoffSearch(ArrayList<Handoff> list, String keyword,
                                        boolean caseMatch, boolean wholeWords){

        ArrayList<Handoff> temp = new ArrayList<Handoff>(list);

        try {
            //get the list of properties for the class
            BeanInfo elogInfo = Introspector.getBeanInfo(Handoff.class);

            for (Handoff item : temp){
                boolean found = false;
                    
                    for (PropertyDescriptor pd : elogInfo.getPropertyDescriptors()) {
                        //for the current property, retrieve its getter
                        Method method = pd.getReadMethod();
                        
                        if (pd.getPropertyType().equals(java.lang.String.class)) {
                            //begin checking the parameters, all self explanatory.
                            if (caseMatch == true && wholeWords == true) {
                                Pattern p = Pattern.compile(".*\\W?\\Q"+keyword+"\\E\\W?.*");
                                Matcher m = p.matcher(method.invoke(item).toString());
                                if (m.matches())
                                    found = true;
                            }
                            else if (caseMatch == false && wholeWords == true) {
                                Pattern p = Pattern.compile(".*\\W?\\Q"+keyword+"\\E\\W?.*", Pattern.CASE_INSENSITIVE);
                                Matcher m = p.matcher(method.invoke(item).toString());
                                System.out.println(m);
                                System.out.println(method.invoke(item).toString());
                                if (m.matches()){
                                    System.out.println("match");
                                    found = true;
                                }
                            }
                            else if (caseMatch == true && wholeWords == false
                                    && method.invoke(item).toString().contains(keyword)) {
                                found = true;
                            }
                            else if (caseMatch == false && wholeWords == false
                                    && method.invoke(item).toString().toLowerCase().contains(keyword.toLowerCase())) {
                                found = true;
                            }
                        }
                    }
                   
                //if there are no fields that match, then the elog is removed
                System.out.println(found);
                if (found == false){
                    list.remove(item);
                }
            }

        } catch (IntrospectionException ex) {
            System.out.println("!!!!!!!");
            Logger.getLogger(SearchGUI.class.getName()).log(Level.SEVERE, null, ex);
        } finally{
            //ALWAYS return elogs back to the calling method.
            return list;
        }
    }

    //get the elogs for all users, no duplicate logs
    private ArrayList<Elog> getUserElogs(String criteria){

        if(selectedUser.equals("All")){
                        /**
                         * This block queries every users elog Repository, checks
                         * for duplicates and adds one of every elog to the master
                         * list.  It checks for duplicates based off of the id number.
                         * It depends on how the elog repositories are designed, if there
                         * is one counter for all of them or if each elog id number only
                         * has meaning within its repository.  This might need to be
                         * looked over once we know for sure.
                         */
                        for(ElogUser currUser : users){
                            ArrayList<Elog> elogHelper = Helper.query(currUser.getReposTitle(), criteria, context);
                            for(Elog elog : elogHelper){
                                if(!elogInArray(elogs, elog)){
                                    elogs.add(elog);
                                }
                            }
                        }
        } else {
            ArrayList<Elog> elogHelper = Helper.query(getReposNameFromUsrName(selectedUser), criteria, context);
            for(Elog elog : elogHelper){
                if(!elogInArray(elogs, elog)){
                    elogs.add(elog);
                }
            }
        }
        return elogs;
    }

    //get the handoofss for all users, no duplicate logs
    private ArrayList<Handoff> getUserHandoffs(String criteria){

        if(selectedUser.equals("All")){
                        /**
                         * This block queries every users handoff Repository, checks
                         * for duplicates and adds one of every handoff to the master
                         * list.  It checks for duplicates based off of the id number.
                         */
                        for(ElogUser currUser : users){
                            ArrayList<Handoff> handoffHelper = Helper.query("Handoffs", criteria, context);
                            for(Handoff handoff : handoffHelper){
                                if(!handoffInArray(handoffs, handoff)){
                                    handoffs.add(handoff);
                                    
                                }
                            }
                        }
        } else {
            ArrayList<Handoff> handoffHelper = Helper.query(getReposNameFromUsrName(selectedUser), criteria, context);
            for(Handoff handoff : handoffHelper){
                if(!handoffInArray(handoffs, handoff)){
                    handoffs.add(handoff);
                }
            }
        }

        return handoffs;
    }

    private String getReposNameFromUsrName(String user){
        for(ElogUser currUser : users){
            if(currUser.getLogname().equals(user)){
                return currUser.getReposTitle();
            }
        }

        return "";
    }

    /*
     * check if an elog is in the supplied array.
     */
    private boolean elogInArray(ArrayList<Elog> elogs, Elog elogCheck){
        
        try{
            BeanInfo elogInfo = Introspector.getBeanInfo(Elog.class);
            for (Elog item : elogs){
                boolean differs = false;
                for (PropertyDescriptor pd : elogInfo.getPropertyDescriptors()) {
                    //for the current property, retrieve its getter
                    Method method = pd.getReadMethod();
                    if(!method.invoke(item).toString().equals(method.invoke(elogCheck).toString()))
                    {
                        differs = true;
                    }
                }
                
                if(!differs){
                    return true;
                }
            }
        } catch(Exception e){
            
        }
        
        return false;
    }

     /*
     * check if a handoff is in the supplied array.
     */
    private boolean handoffInArray(ArrayList<Handoff> handoffs, Handoff handoffCheck){
        
        try{
            BeanInfo elogInfo = Introspector.getBeanInfo(Handoff.class);
            for (Handoff item : handoffs){
                boolean differs = false;
                for (PropertyDescriptor pd : elogInfo.getPropertyDescriptors()) {
                    //for the current property, retrieve its getter
                    Method method = pd.getReadMethod();
                    if(!method.invoke(item).toString().equals(method.invoke(handoffCheck).toString()))
                    {
                        differs = true;
                    }
                }
                
                if(!differs){
                    return true;
                }
            }
        } catch(Exception e){
            
        }
        
        return false;
    }

    /*
     * Launches the searchResults table using the table model.
     */
    private void launchResults(final JFrame table){
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {

                // this passes the elog results through to the Search Table
                // results controler which pipes it directly into the Model.

                if(!elogs.isEmpty()){
                    SearchResultsTableModel.setData(elogs);
                    SearchTableResults dialog = new SearchTableResults(table);

                    dialog.setVisible(true);
                } else{
                        String message = "No search results found.";
                        JOptionPane.showMessageDialog(table, message, "Search",
                        JOptionPane.ERROR_MESSAGE); 
                }
            }
        });
    }

    private void statusComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_statusComboBoxActionPerformed
        // TODO add your handling code here:
        String selectedItem = (String) statusComboBox.getSelectedItem();
        status = Elog.Status.valueOf(selectedItem);
    }//GEN-LAST:event_statusComboBoxActionPerformed

    private void endCalendarButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_endCalendarButtonActionPerformed
        // TODO add your handling code here:

    }//GEN-LAST:event_endCalendarButtonActionPerformed

    private void startCalendarButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startCalendarButtonActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_startCalendarButtonActionPerformed

    private void startCalendarButtonFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_startCalendarButtonFocusLost
        String date = startTimeTextField.getText();
        setStartDate(date);
    }//GEN-LAST:event_startCalendarButtonFocusLost

    private void startCalendarButtonPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_startCalendarButtonPropertyChange
         if (evt.getNewValue() instanceof Date)
            setStartDate((Date)evt.getNewValue());
    }//GEN-LAST:event_startCalendarButtonPropertyChange

    private void endCalendarButtonFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_endCalendarButtonFocusLost
        String date = endTimeTextField.getText();
        setEndDate(date);
    }//GEN-LAST:event_endCalendarButtonFocusLost

    private void endCalendarButtonPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_endCalendarButtonPropertyChange
        if (evt.getNewValue() instanceof Date)
            setEndDate((Date)evt.getNewValue());
    }//GEN-LAST:event_endCalendarButtonPropertyChange

    private void userComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_userComboBoxActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_userComboBoxActionPerformed
     public static void main(String args[]){
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
                } catch (Exception e){

                }

            final SearchGUI search = new SearchGUI();
            search.setSize(330, 410);

            search.addWindowListener(new java.awt.event.WindowAdapter() {
                @Override
                public void windowClosing(java.awt.event.WindowEvent e) {

                    System.exit(0);

                }
            });

            search.setVisible(true);
        }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cancelButton;
    private org.jbundle.thin.base.screen.jcalendarbutton.JCalendarButton endCalendarButton;
    private javax.swing.JLabel endTimeLabel;
    private javax.swing.JTextField endTimeTextField;
    private javax.swing.JCheckBox findWholeWordsOnlyCheckBox;
    private javax.swing.JButton goButton;
    private javax.swing.JFrame jFrame1;
    private javax.swing.JFrame jFrame2;
    private javax.swing.JLabel keywordLabel;
    private javax.swing.JTextField keywordTextField;
    private javax.swing.JCheckBox matchCaseCheckBox;
    private javax.swing.JCheckBox searchByIdCheckBox;
    private javax.swing.JLabel searchByIdLabel;
    public javax.swing.JTextField searchByIdTextField;
    private javax.swing.JCheckBox searchHandoffsCheckBox;
    private org.jbundle.thin.base.screen.jcalendarbutton.JCalendarButton startCalendarButton;
    private javax.swing.JLabel startTimeLabel;
    private javax.swing.JTextField startTimeTextField;
    private javax.swing.JComboBox statusComboBox;
    private javax.swing.JLabel statusLabel;
    private javax.swing.JComboBox typeComboBox;
    private javax.swing.JLabel typeLabel;
    private javax.swing.JComboBox userComboBox;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables

    //Formats date in mm/dd/yyyy format.
    public static SimpleDateFormat dateFormat = new SimpleDateFormat("MM / dd / yyyy");

    public void setStartDate(String dateString) {
        Date date = null;
        try {
            if ((dateString != null) && (dateString.length() > 0)) {
                date = dateFormat.parse(dateString);
            }
        } catch (Exception e) {
            date = null;
        }
        this.setStartDate(date);
    }

    /**
     * Validate and set the datetime field on the screen given a startDate.
     * @param date 
     */
    public void setStartDate(Date date) {
        String dateString = "";
        if (date != null) {
            dateString = dateFormat.format(date);
        }
        startTimeTextField.setText(dateString);
        startCalendarButton.setTargetDate(date);
    }

    /**
     * Validate and set the datetime field on the screen given a datetime string.
     * @param dateString
     */
    public void setEndDate(String dateString) {
        Date date = null;
        try {
            if ((dateString != null) && (dateString.length() > 0)) {
                date = dateFormat.parse(dateString);
            }
        } catch (Exception e) {
            date = null;
        }
        this.setEndDate(date);
    }

    /**
     * Validate and set the datetime field on the screen given a startDate.
     * @param date
     */
    public void setEndDate(Date date) {
        String dateString = "";
        if (date != null) {
            dateString = dateFormat.format(date);
        }
        endTimeTextField.setText(dateString);
        endCalendarButton.setTargetDate(date);
    }

}

